﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OWLServer.owl.tipos;
using System.Xml.Linq;
using OWLServer.owl.etiquetas;

namespace OWLServer.owl.utilidades
{
    /// <summary>
    /// Clase que contiene métodos para manejar los elementos de una ontología.
    /// </summary>
    class UtilidadesElementos
    {
        private const char CARACTER_SERADOR_URI_OBJETO = '#';
        private const string CADENA_VACIA = "";

        /// <summary>
        /// Crea un Elemento partiendo de un XElement
        /// </summary>
        /// <param name="id">Identificador del elemento</param>
        /// <param name="ontologia">Ontologia obtenida el OWL</param>
        /// <returns>Elemento del OWL</returns>
        public static Elemento getElemento(string id, Ontologia ontologia)
        {
            Elemento elemento = null;

            if (string.Empty != id)
            {
                // Partimos por el caracter #
                string[] partes = id.Split(CARACTER_SERADOR_URI_OBJETO);
                if (partes.Length == 2)
                {
                    // La pimera parte es la URI del espacio de nombres y la segunda es el Id de la propiedad
                    string uri = partes[0];
                    string nombre = partes[1];

                    elemento = new Elemento(nombre);

                    if (uri == CADENA_VACIA)
                    {
                        // Eso quiere decir que pertenece al espacio de nombres base de la ontología
                        elemento.EspacioNombres = ontologia.EspacioNombresPrincipal;
                    }
                    else
                    {
                        StringBuilder sbUri = null;
                        // Si no quiere decir que tiene otro espacio
                        foreach (EspacioNombres espacio in ontologia.EspaciosNombres)
                        {
                            sbUri = new StringBuilder();
                            sbUri.Append(uri);
                            sbUri.Append(CARACTER_SERADOR_URI_OBJETO);
                            if (espacio.Uri == sbUri.ToString())
                            {
                                elemento.EspacioNombres = espacio;
                            }
                        }
                    }
                }
                else
                {
                    // Al no pertenecer a un espacio de nombres conocido lo asociamos al principal
                    elemento = new Elemento(id);
                    elemento.EspacioNombres = ontologia.EspacioNombresPrincipal;
                }
            }

            return elemento;
        }

        /// <summary>
        /// Obtiene el Id de un elemento
        /// </summary>
        /// <param name="espaciosNombres">Espacios de nombres que tienen la ontología</param>
        /// <param name="element">Elemento de entrada</param>
        /// <returns>Cadena que representa el Id del elemento</returns>
        public static string getId(XElement element, IDictionary<string, EspacioNombres> espaciosNombres)
        {
            string id = string.Empty;

            id = element.Attribute(UtilidadesEspaciosNombres.getEspacioNombres(espaciosNombres[EtiquetasRDF.NOMBRE]) + EtiquetasRDF.ABOUT).Value;

            return id;
        }

        /// <summary>
        /// Obtiene el atributo Recurso del Elemento
        /// </summary>
        /// <param name="espaciosNombres">Espacios de nombres que tienen la ontología</param>
        /// <param name="element">Elemento de entrada</param>
        /// <returns>Cadena que representa el Recurso del elemento</returns>
        public static string getNombreRecurso(XElement element, IDictionary<string, EspacioNombres> espaciosNombres)
        {
            string id = "";

            XAttribute atributoRecurso = element.Attribute(UtilidadesEspaciosNombres.getEspacioNombres(espaciosNombres[EtiquetasRDF.NOMBRE]) + EtiquetasRDF.RECURSO);

            if (null != atributoRecurso)
            {
                id = atributoRecurso.Value;
            }

            return id;
        }

        /// <summary>
        /// Indica si el elemento Description que le pasamos es el tipo que le indicamos
        /// </summary>
        /// <param name="elementoDescripcion">Elemento Description a analizar</param>
        /// <param name="tipo">Tipo que estamos buscando</param>
        /// <param name="ontologia">Ontología que estamos analizando</param>
        /// <returns>Indica si es del tipo o no</returns>
        public static bool isElementoDescripcionTipo(XElement elementoDescripcion, string tipo, Ontologia ontologia)
        {
            bool isTipo = false;
            Elemento recurso;

            // Vemos el tipo de Descripcion
            IEnumerable<XElement> eleTiposDescipcion =
                from el in elementoDescripcion.Elements(UtilidadesEspaciosNombres.getEspacioNombres(ontologia.getEspaciosNombresDictiorary()[EtiquetasRDF.NOMBRE]) + EtiquetasRDF.TIPO)
                select el;

            foreach (XElement eleTipoDescipcion in eleTiposDescipcion)
            {
                recurso = UtilidadesElementos.getElemento(UtilidadesElementos.getNombreRecurso(eleTipoDescipcion, ontologia.getEspaciosNombresDictiorary()), ontologia);
                if (ontologia.getEspaciosNombresDictiorary()[EtiquetasOWL.NOMBRE].Equals(recurso.EspacioNombres))
                {
                    if (recurso.Id == tipo)
                    {
                        isTipo = true;
                    }
                }
            }

            return isTipo;
        }
    }
}
